{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "699c7cc2-77ce-44ce-b348-b3557ed155cd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "72c6387b18a5463698d40ae1e43827a9",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "GraphWidget(layout=Layout(height='650px', width='100%'))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import asyncio\n",
    "\n",
    "import pandas as pd\n",
    "import tiktoken\n",
    "from IPython.display import Markdown,display\n",
    "\n",
    "from graphrag.query.context_builder.entity_extraction import EntityVectorStoreKey\n",
    "from graphrag.query.indexer_adapters import (\n",
    "    read_indexer_entities,\n",
    "    read_indexer_relationships,\n",
    "    read_indexer_reports,\n",
    "    read_indexer_text_units, read_indexer_communities,\n",
    ")\n",
    "from graphrag.query.llm.oai.chat_openai import ChatOpenAI\n",
    "from graphrag.query.llm.oai.embedding import OpenAIEmbedding\n",
    "from graphrag.query.llm.oai.typing import OpenaiApiType\n",
    "from graphrag.query.structured_search.global_search.community_context import GlobalCommunityContext\n",
    "from graphrag.query.structured_search.global_search.search import GlobalSearch\n",
    "from graphrag.query.structured_search.local_search.mixed_context import (\n",
    "    LocalSearchMixedContext,\n",
    ")\n",
    "from graphrag.query.structured_search.local_search.search import LocalSearch\n",
    "from graphrag.vector_stores.lancedb import LanceDBVectorStore\n",
    "\n",
    "INPUT_DIR = \"./openl1/output\"\n",
    "LANCEDB_URI = f\"{INPUT_DIR}/lancedb\"\n",
    "\n",
    "COMMUNITY_REPORT_TABLE = \"create_final_community_reports\"\n",
    "ENTITY_TABLE = \"create_final_nodes\"\n",
    "ENTITY_EMBEDDING_TABLE = \"create_final_entities\"\n",
    "RELATIONSHIP_TABLE = \"create_final_relationships\"\n",
    "TEXT_UNIT_TABLE = \"create_final_text_units\"\n",
    "COMMUNITY_LEVEL = 2\n",
    "\n",
    "COMMUNITY_TABLE = \"create_final_communities\"\n",
    "\n",
    "community_df = pd.read_parquet(f\"{INPUT_DIR}/{COMMUNITY_TABLE}.parquet\")\n",
    "entity_df = pd.read_parquet(f\"{INPUT_DIR}/{ENTITY_TABLE}.parquet\")\n",
    "report_df = pd.read_parquet(f\"{INPUT_DIR}/{COMMUNITY_REPORT_TABLE}.parquet\")\n",
    "entity_embedding_df = pd.read_parquet(f\"{INPUT_DIR}/{ENTITY_EMBEDDING_TABLE}.parquet\")\n",
    "relationship_df = pd.read_parquet(f\"{INPUT_DIR}/{RELATIONSHIP_TABLE}.parquet\")\n",
    "\n",
    "\n",
    "communities = read_indexer_communities(community_df, entity_df, report_df)\n",
    "reports = read_indexer_reports(report_df, entity_df, COMMUNITY_LEVEL)\n",
    "entities = read_indexer_entities(entity_df, entity_embedding_df, COMMUNITY_LEVEL)\n",
    "relationships = read_indexer_relationships(relationship_df)\n",
    "\n",
    "def convert_entities_to_dicts(df):\n",
    "    \"\"\"Convert the entities dataframe to a list of dicts for yfiles-jupyter-graphs.\"\"\"\n",
    "    nodes_dict = {}\n",
    "    for _, row in df.iterrows():\n",
    "        # Create a dictionary for each row and collect unique nodes\n",
    "        node_id = row[\"title\"]\n",
    "        if node_id not in nodes_dict:\n",
    "            nodes_dict[node_id] = {\n",
    "                \"id\": node_id,\n",
    "                \"properties\": row.to_dict(),\n",
    "            }\n",
    "    return list(nodes_dict.values())\n",
    "\n",
    "def convert_relationships_to_dicts(df):\n",
    "    \"\"\"Convert the relationships dataframe to a list of dicts for yfiles-jupyter-graphs.\"\"\"\n",
    "    relationships = []\n",
    "    for _, row in df.iterrows():\n",
    "        # Create a dictionary for each row\n",
    "        relationships.append({\n",
    "            \"start\": row[\"source\"],\n",
    "            \"end\": row[\"target\"],\n",
    "            \"properties\": row.to_dict(),\n",
    "        })\n",
    "    return relationships\n",
    "\n",
    "convert_relationships_to_dicts(relationship_df)[0]\n",
    "\n",
    "from yfiles_jupyter_graphs import GraphWidget\n",
    "\n",
    "w = GraphWidget()    # 创建GraphWidget对象\n",
    "w.directed = True    # 设置图形为有向图\n",
    "w.nodes = convert_entities_to_dicts(entity_df) # 将实体数据转换为节点\n",
    "w.edges = convert_relationships_to_dicts(relationship_df) # 将关系数据转换为边\n",
    "\n",
    "\n",
    "w.node_label_mapping = \"title\"  # 设置节点标签显示\n",
    "\n",
    "# 社区到颜色的映射\n",
    "def community_to_color(community):\n",
    "    \"\"\"Map a community to a color.\"\"\"\n",
    "    colors = [\n",
    "        \"crimson\",\n",
    "        \"darkorange\",\n",
    "        \"indigo\",\n",
    "        \"cornflowerblue\",\n",
    "        \"cyan\",\n",
    "        \"teal\",\n",
    "        \"green\",\n",
    "    ]\n",
    "    try:\n",
    "        return colors[int(community) % len(colors)] if community is not None else \"lightgray\"\n",
    "    except (ValueError, TypeError):\n",
    "        # 如果 community 不是整数或其他错误，返回默认颜色\n",
    "        return \"lightgray\"\n",
    "\n",
    "\n",
    "def edge_to_source_community(edge):\n",
    "    \"\"\"Get the community of the source node of an edge.\"\"\"\n",
    "    source_node = next(\n",
    "        (entry for entry in w.nodes if entry[\"properties\"][\"title\"] == edge[\"start\"]),\n",
    "        None,\n",
    "    )\n",
    "    source_node_community = source_node[\"properties\"][\"community\"]\n",
    "    return source_node_community if source_node_community is not None else None\n",
    "\n",
    "\n",
    "w.node_color_mapping = lambda node: community_to_color(\n",
    "    node[\"properties\"].get(\"community\", None)  # 使用 .get 方法获取属性，避免 KeyError\n",
    ")\n",
    "w.edge_color_mapping = lambda edge: community_to_color(edge_to_source_community(edge))\n",
    "\n",
    "w.node_scale_factor_mapping = lambda node: 0.5 + node[\"properties\"].get(\"size\", 1) * 1.5 / 20\n",
    "\n",
    "w.edge_thickness_factor_mapping = \"weight\"\n",
    "\n",
    "\n",
    "w.circular_layout()\n",
    "\n",
    "display(w)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c0d78036-092c-47bf-8aa0-967d3ad25adf",
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Entity count: 15\n",
      "                                     id  human_readable_id    title  \\\n",
      "0  e53d0b92-5b1a-414a-9759-1ae3668d7573                  0      ID3   \n",
      "1  43a0224c-00c7-4c09-b555-208611522c50                  1     C4.5   \n",
      "2  fb20e92a-f612-4e19-b3a2-39a14e0d4369                  2     CART   \n",
      "3  472a3ae3-dbaf-46cf-8759-19b87130b956                  3  SKLEARN   \n",
      "4  a9dfe93b-cd03-48fc-9dc2-1cd574ba2e11                  4    NUMPY   \n",
      "\n",
      "   community  level  degree  x  y  \n",
      "0          3      0       7  0  0  \n",
      "1          0      0      13  0  0  \n",
      "2          1      0       4  0  0  \n",
      "3          1      0       3  0  0  \n",
      "4          3      0       2  0  0  \n",
      "Relationship count: 25\n",
      "                                     id  human_readable_id source  \\\n",
      "0  0de505c8-acf9-4ad1-8589-dc55512e9460                  0    ID3   \n",
      "1  e16f3554-99e0-4d7d-8cd6-8262203b83fa                  1    ID3   \n",
      "2  d2120011-f114-4ea6-91f2-3f684f79e585                  2    ID3   \n",
      "3  aaf8afd4-91fe-4fdd-b0bd-6ee16ef4d233                  3    ID3   \n",
      "4  889c7c85-b8cc-4a07-aeb3-3be84193e641                  4    ID3   \n",
      "\n",
      "                target                                        description  \\\n",
      "0                 C4.5  **ID3 and C4.5** are decision tree algorithms ...   \n",
      "1                 CART  Both ID3 and CART are decision tree algorithms...   \n",
      "2              SKLEARN    Scikit-learn does not support the ID3 algorithm   \n",
      "3  INFORMATION ENTROPY  ID3 uses information entropy as its primary pu...   \n",
      "4     INFORMATION GAIN  ID3 selects splits based on maximum informatio...   \n",
      "\n",
      "   weight  combined_degree                                      text_unit_ids  \n",
      "0     9.0               20  [4ba5acd798a419708cfe5cc86f1fcb6df907a20b1992a...  \n",
      "1     1.0               11  [4ba5acd798a419708cfe5cc86f1fcb6df907a20b1992a...  \n",
      "2     1.0               10  [4ba5acd798a419708cfe5cc86f1fcb6df907a20b1992a...  \n",
      "3     1.0                9  [4ba5acd798a419708cfe5cc86f1fcb6df907a20b1992a...  \n",
      "4     1.0               11  [4ba5acd798a419708cfe5cc86f1fcb6df907a20b1992a...  \n",
      "Report records: 4\n",
      "                                 id  human_readable_id  community  parent  \\\n",
      "0  abe6f076d8d345eb9e8811156579e503                  0          0      -1   \n",
      "1  11fabb4136c048ec81a2a9ddb464e6fb                  1          1      -1   \n",
      "2  24690fdd87664cbf945aca941f79cf44                  2          2      -1   \n",
      "3  1f5f79b05f55441baed7e9d103352840                  3          3      -1   \n",
      "\n",
      "   level                                              title  \\\n",
      "0      0        C4.5 and Decision Tree Algorithms Community   \n",
      "1      0  GR, SKLEARN, and CART in Decision Tree Algorithms   \n",
      "2      0    Information Metrics in Decision Tree Algorithms   \n",
      "3      0    ID3 and C4.5 Decision Tree Algorithms Community   \n",
      "\n",
      "                                             summary  \\\n",
      "0  The community centers around the C4.5 decision...   \n",
      "1  The community centers around key entities in t...   \n",
      "2  The community centers around key information m...   \n",
      "3  The community centers around the ID3 and C4.5 ...   \n",
      "\n",
      "                                        full_content  rank  \\\n",
      "0  # C4.5 and Decision Tree Algorithms Community\\...   7.5   \n",
      "1  # GR, SKLEARN, and CART in Decision Tree Algor...   7.5   \n",
      "2  # Information Metrics in Decision Tree Algorit...   7.5   \n",
      "3  # ID3 and C4.5 Decision Tree Algorithms Commun...   7.5   \n",
      "\n",
      "                                    rank_explanation  \\\n",
      "0  The impact severity rating is high due to C4.5...   \n",
      "1  The impact severity rating is high due to the ...   \n",
      "2  The impact severity rating is high due to the ...   \n",
      "3  The impact severity rating is high due to the ...   \n",
      "\n",
      "                                            findings  \\\n",
      "0  [{'explanation': 'C4.5 stands out as a central...   \n",
      "1  [{'explanation': 'GR (Gain Ratio) is a critica...   \n",
      "2  [{'explanation': 'INFORMATION GAIN is a fundam...   \n",
      "3  [{'explanation': 'ID3 is a classic decision tr...   \n",
      "\n",
      "                                   full_content_json      period  size  \n",
      "0  {\\n    \"title\": \"C4.5 and Decision Tree Algori...  2025-04-06     5  \n",
      "1  {\\n    \"title\": \"GR, SKLEARN, and CART in Deci...  2025-04-06     3  \n",
      "2  {\\n    \"title\": \"Information Metrics in Decisi...  2025-04-06     3  \n",
      "3  {\\n    \"title\": \"ID3 and C4.5 Decision Tree Al...  2025-04-06     4  \n",
      "Text unit records: 4\n",
      "                                                  id  human_readable_id  \\\n",
      "0  4ba5acd798a419708cfe5cc86f1fcb6df907a20b1992ad...                  1   \n",
      "1  7a8436d7970da4b0e5c837b0a3eaaa196e6e2284c7c754...                  2   \n",
      "2  1141affdc56bf8f5092b950b57febdedb884673ec6b23d...                  3   \n",
      "3  b5df95b6ec7e3aaea3f67db4914e1b2e874f3ac77fc3c8...                  4   \n",
      "\n",
      "                                                text  n_tokens  \\\n",
      "0  Lesson 8.3 ID3、C4.5决策树的建模流程\\nID3和C4.5作为的经典决策树算...      1200   \n",
      "1  8961919\\n然后即可算出按照如此规则进行数据集划分，最终能够减少的不纯度数值：\\n# ...      1200   \n",
      "2  4.5决策树的基本建模流程\\n作为ID3的改进版算法，C4.5在ID3的基础上进行了三个方面...      1200   \n",
      "3  集划分。\\n\\nC4.5的连续变量处理方法\\nC4.5允许带入连续变量进行建模，并且围绕连续...       558   \n",
      "\n",
      "                                        document_ids  \\\n",
      "0  [2ef33abc7acb307f736e46c7f20fe87568b4e9bd6311c...   \n",
      "1  [2ef33abc7acb307f736e46c7f20fe87568b4e9bd6311c...   \n",
      "2  [2ef33abc7acb307f736e46c7f20fe87568b4e9bd6311c...   \n",
      "3  [2ef33abc7acb307f736e46c7f20fe87568b4e9bd6311c...   \n",
      "\n",
      "                                          entity_ids  \\\n",
      "0  [e53d0b92-5b1a-414a-9759-1ae3668d7573, 43a0224...   \n",
      "1                                               None   \n",
      "2  [e53d0b92-5b1a-414a-9759-1ae3668d7573, 43a0224...   \n",
      "3  [43a0224c-00c7-4c09-b555-208611522c50, fb20e92...   \n",
      "\n",
      "                                    relationship_ids  \n",
      "0  [0de505c8-acf9-4ad1-8589-dc55512e9460, e16f355...  \n",
      "1                                               None  \n",
      "2  [0de505c8-acf9-4ad1-8589-dc55512e9460, 2b732d3...  \n",
      "3  [2b732d3b-0a69-45c6-943d-b3064227ad1a, e93e51b...  \n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "根据提供的文档内容，总共介绍了三种主要的决策树算法：\n",
       "\n",
       "### 1. ID3算法\n",
       "ID3（Iterative Dichotomiser 3）是最早的决策树算法之一，专门用于解决分类问题，尤其擅长处理离散变量。它使用信息熵（Information Entropy）作为纯度评估指标来构建决策树。然而，ID3存在一些局限性，比如无法处理连续变量、不支持回归问题，并且容易过拟合 [Data: Entities (0); Relationships (3); Reports (3)].\n",
       "\n",
       "### 2. C4.5算法\n",
       "C4.5是ID3的改进版本，解决了ID3的多个缺点。它引入了以下关键改进：\n",
       "- 能够处理连续变量，通过寻找相邻值的中间点作为切分点 [Data: Sources (3)].\n",
       "- 使用增益比例（Gain Ratio, GR）代替信息增益（Information Gain），通过信息值（Information Value, IV）修正信息增益的计算，减少对多分支特征的偏好 [Data: Entities (10, 8); Relationships (14, 19)].\n",
       "- 支持剪枝技术，提高模型的泛化能力 [Data: Reports (0, 3)].\n",
       "\n",
       "C4.5仍然主要用于分类问题，但其灵活性和性能使其成为决策树算法中的重要里程碑 [Data: Entities (1); Relationships (0, 18)].\n",
       "\n",
       "### 3. CART算法\n",
       "CART（Classification and Regression Trees）是另一种广泛使用的决策树算法，与ID3和C4.5有以下区别：\n",
       "- 支持分类和回归任务，而ID3和C4.5仅支持分类 [Data: Entities (2)].\n",
       "- 使用不同的纯度评估指标（如基尼不纯度）和分裂方法 [Data: Relationships (1)].\n",
       "- 被Scikit-learn（SKLEARN）采用作为默认的决策树实现，而SKLEARN不支持ID3和C4.5 [Data: Entities (3); Relationships (12)].\n",
       "\n",
       "### 总结\n",
       "文档中明确提到的决策树算法包括：\n",
       "1. ID3  \n",
       "2. C4.5  \n",
       "3. CART  \n",
       "\n",
       "这些算法在功能、适用场景和技术细节上各有特点，共同构成了决策树方法的核心体系 [Data: Reports (0, 3); Entities (0, 1, 2); Relationships (0, 1, 7, 12)]."
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "async def localSearch():\n",
    "    ####################################################################################\n",
    "    # read nodes table to get community and degree data\n",
    "    entity_df = pd.read_parquet(f\"{INPUT_DIR}/{ENTITY_TABLE}.parquet\")\n",
    "    entity_embedding_df = pd.read_parquet(f\"{INPUT_DIR}/{ENTITY_EMBEDDING_TABLE}.parquet\")\n",
    "\n",
    "    entities = read_indexer_entities(entity_df, entity_embedding_df, COMMUNITY_LEVEL)\n",
    "\n",
    "    # load description embeddings to an in-memory lancedb vectorstore\n",
    "    # to connect to a remote db, specify url and port values.\n",
    "    description_embedding_store = LanceDBVectorStore(\n",
    "        collection_name=\"default-entity-description\",\n",
    "    )\n",
    "    description_embedding_store.connect(db_uri=LANCEDB_URI)\n",
    "\n",
    "    print(f\"Entity count: {len(entity_df)}\")\n",
    "    print(entity_df.head())\n",
    "\n",
    "    ####################################################################################\n",
    "    relationship_df = pd.read_parquet(f\"{INPUT_DIR}/{RELATIONSHIP_TABLE}.parquet\")\n",
    "    relationships = read_indexer_relationships(relationship_df)\n",
    "\n",
    "    print(f\"Relationship count: {len(relationship_df)}\")\n",
    "    print(relationship_df.head())\n",
    "\n",
    "    ####################################################################################\n",
    "    report_df = pd.read_parquet(f\"{INPUT_DIR}/{COMMUNITY_REPORT_TABLE}.parquet\")\n",
    "    reports = read_indexer_reports(report_df, entity_df, COMMUNITY_LEVEL)\n",
    "\n",
    "    print(f\"Report records: {len(report_df)}\")\n",
    "    print(report_df.head())\n",
    "\n",
    "    ####################################################################################\n",
    "\n",
    "    text_unit_df = pd.read_parquet(f\"{INPUT_DIR}/{TEXT_UNIT_TABLE}.parquet\")\n",
    "    text_units = read_indexer_text_units(text_unit_df)\n",
    "\n",
    "    print(f\"Text unit records: {len(text_unit_df)}\")\n",
    "    print(text_unit_df.head())\n",
    "\n",
    "    ####################################################################################\n",
    "    llm_api_key = \"sk-36f1e4fd00844220a6cebde72bb87afd\"\n",
    "    embeding_api_key = \"0d28f030249b4fe38dc501510748b595.9SGm9tuJBlcgqKBm\"\n",
    "\n",
    "    llm_model = \"deepseek-chat\"\n",
    "    embedding_model = \"embedding-3\"\n",
    "\n",
    "    llm_api_base = \"https://api.deepseek.com\"\n",
    "    embedding_model_api_base = \"https://open.bigmodel.cn/api/paas/v4/\"\n",
    "\n",
    "\n",
    "    llm = ChatOpenAI(\n",
    "        api_key=llm_api_key,\n",
    "        model=llm_model,\n",
    "        api_base=llm_api_base,\n",
    "        api_type=OpenaiApiType.OpenAI,\n",
    "        max_retries=20,\n",
    "    )\n",
    "\n",
    "    token_encoder = tiktoken.get_encoding(\"cl100k_base\")\n",
    "\n",
    "    text_embedder = OpenAIEmbedding(\n",
    "        api_key=embeding_api_key,\n",
    "        api_base=embedding_model_api_base,\n",
    "        api_type=OpenaiApiType.OpenAI,\n",
    "        model=embedding_model,\n",
    "        deployment_name=embedding_model,\n",
    "        max_retries=20,\n",
    "    )\n",
    "\n",
    "    context_builder = LocalSearchMixedContext(\n",
    "        community_reports=reports,\n",
    "        text_units=text_units,\n",
    "        entities=entities,\n",
    "        relationships=relationships,\n",
    "        covariates=None,\n",
    "        entity_text_embeddings=description_embedding_store,\n",
    "        embedding_vectorstore_key=EntityVectorStoreKey.ID,\n",
    "        text_embedder=text_embedder,\n",
    "        token_encoder=token_encoder,\n",
    "    )\n",
    "\n",
    "    local_context_params = {\n",
    "        \"text_unit_prop\": 0.5,\n",
    "        \"community_prop\": 0.1,\n",
    "        \"conversation_history_max_turns\": 5,\n",
    "        \"conversation_history_user_turns_only\": True,\n",
    "        \"top_k_mapped_entities\": 10,\n",
    "        \"top_k_relationships\": 10,\n",
    "        \"include_entity_rank\": True,\n",
    "        \"include_relationship_weight\": True,\n",
    "        \"include_community_rank\": True,\n",
    "        \"return_candidate_context\": True,\n",
    "        \"embedding_vectorstore_key\": EntityVectorStoreKey.ID,\n",
    "        \"max_tokens\": 12_000,\n",
    "    }\n",
    "\n",
    "    llm_params = {\n",
    "        \"max_tokens\": 2_000,\n",
    "        \"temperature\": 0.0,\n",
    "    }\n",
    "\n",
    "    search_engine = LocalSearch(\n",
    "        llm=llm,\n",
    "        context_builder=context_builder,\n",
    "        token_encoder=token_encoder,\n",
    "        llm_params=llm_params,\n",
    "        context_builder_params=local_context_params,\n",
    "        response_type=\"multiple paragraphs\",\n",
    "    )\n",
    "\n",
    "    #同步执行正面的方法\n",
    "    # result =  await search_engine.asearch(\"请帮我介绍下ID3决策树算法\")\n",
    "    # print(result.response)\n",
    "        \n",
    "    result = await search_engine.asearch(\"请问文档中总共介绍了几种决策树算法？\")\n",
    "    display(Markdown(result.response))\n",
    "\n",
    "await localSearch()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "c2a6b3b3-8064-4e3e-a648-97e5c927102d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "# 决策树算法应用前景分析\n",
       "\n",
       "基于文档中提供的信息，我将对ID3、C4.5和CART三种决策树算法的应用前景进行分析比较。\n",
       "\n",
       "## C4.5算法的优势\n",
       "\n",
       "从文档内容来看，**C4.5算法**在当前应用场景中展现出最强的综合能力和应用前景。作为ID3的改进版本，C4.5在多个关键方面进行了重要优化：\n",
       "\n",
       "1. **处理连续变量的能力**：C4.5引入了类似CART的连续变量处理方法，通过在连续变量中寻找相邻取值的中间点作为备选切分点，大大扩展了算法的适用范围[Data: Sources (2,3); Reports (0,3)]。\n",
       "\n",
       "2. **改进的划分标准**：C4.5使用增益比例(GR)代替原始信息增益，通过引入信息值(IV)来修正信息增益的计算结果，有效抑制了ID3倾向于选择多分支特征的缺点，减少了过拟合风险[Data: Entities (8,10); Relationships (13,14,15)]。\n",
       "\n",
       "3. **剪枝技术的引入**：相比ID3，C4.5加入了决策树剪枝流程，进一步提升了模型的泛化能力[Data: Sources (2)]。\n",
       "\n",
       "## 与其他算法的比较\n",
       "\n",
       "与**ID3**相比，C4.5解决了ID3只能处理离散变量、容易过拟合等关键缺陷[Data: Relationships (0,18); Entities (0,1)]。虽然ID3作为基础算法仍有教育价值，但在实际应用中已显得局限。\n",
       "\n",
       "与**CART**相比，C4.5保留了处理离散变量的优势，同时借鉴了CART处理连续变量的方法[Data: Relationships (7); Entities (2)]。值得注意的是，主流机器学习库如scikit-learn选择实现CART而非C4.5[Data: Relationships (8,12); Entities (3)]，这可能更多出于实现复杂度和历史原因，而非算法优劣。\n",
       "\n",
       "## 实际应用建议\n",
       "\n",
       "对于需要处理混合类型(离散+连续)特征且追求模型解释性的场景，C4.5仍然是很好的选择。其规则提取方式直观，生成的决策树易于理解[Data: Reports (0)]。\n",
       "\n",
       "然而，在实际工业应用中，需要考虑算法实现的可获得性。由于scikit-learn等主流库未原生支持C4.5，可能需要自行实现或寻找专门库，这在一定程度上限制了其应用[Data: Relationships (8,12)]。\n",
       "\n",
       "综合来看，**C4.5在算法设计上最具前瞻性和全面性**，特别适合需要处理混合数据类型且重视模型解释性的场景。但随着集成学习方法(如随机森林)的普及，单纯决策树算法的应用正在被更强大的集成方案所补充。"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "async def localSearch():\n",
    "    ####################################################################################\n",
    "    # read nodes table to get community and degree data\n",
    "    entity_df = pd.read_parquet(f\"{INPUT_DIR}/{ENTITY_TABLE}.parquet\")\n",
    "    entity_embedding_df = pd.read_parquet(f\"{INPUT_DIR}/{ENTITY_EMBEDDING_TABLE}.parquet\")\n",
    "\n",
    "    entities = read_indexer_entities(entity_df, entity_embedding_df, COMMUNITY_LEVEL)\n",
    "\n",
    "    # load description embeddings to an in-memory lancedb vectorstore\n",
    "    # to connect to a remote db, specify url and port values.\n",
    "    description_embedding_store = LanceDBVectorStore(\n",
    "        collection_name=\"default-entity-description\",\n",
    "    )\n",
    "    description_embedding_store.connect(db_uri=LANCEDB_URI)\n",
    "\n",
    "    ####################################################################################\n",
    "    relationship_df = pd.read_parquet(f\"{INPUT_DIR}/{RELATIONSHIP_TABLE}.parquet\")\n",
    "    relationships = read_indexer_relationships(relationship_df)\n",
    "\n",
    "    ####################################################################################\n",
    "    report_df = pd.read_parquet(f\"{INPUT_DIR}/{COMMUNITY_REPORT_TABLE}.parquet\")\n",
    "    reports = read_indexer_reports(report_df, entity_df, COMMUNITY_LEVEL)\n",
    "\n",
    "    ####################################################################################\n",
    "\n",
    "    text_unit_df = pd.read_parquet(f\"{INPUT_DIR}/{TEXT_UNIT_TABLE}.parquet\")\n",
    "    text_units = read_indexer_text_units(text_unit_df)\n",
    "\n",
    "    ####################################################################################\n",
    "    llm_api_key = \"sk-36f1e4fd00844220a6cebde72bb87afd\"\n",
    "    embeding_api_key = \"0d28f030249b4fe38dc501510748b595.9SGm9tuJBlcgqKBm\"\n",
    "\n",
    "    llm_model = \"deepseek-chat\"\n",
    "    embedding_model = \"embedding-3\"\n",
    "\n",
    "    llm_api_base = \"https://api.deepseek.com\"\n",
    "    embedding_model_api_base = \"https://open.bigmodel.cn/api/paas/v4/\"\n",
    "\n",
    "\n",
    "    llm = ChatOpenAI(\n",
    "        api_key=llm_api_key,\n",
    "        model=llm_model,\n",
    "        api_base=llm_api_base,\n",
    "        api_type=OpenaiApiType.OpenAI,\n",
    "        max_retries=20,\n",
    "    )\n",
    "\n",
    "    token_encoder = tiktoken.get_encoding(\"cl100k_base\")\n",
    "\n",
    "    text_embedder = OpenAIEmbedding(\n",
    "        api_key=embeding_api_key,\n",
    "        api_base=embedding_model_api_base,\n",
    "        api_type=OpenaiApiType.OpenAI,\n",
    "        model=embedding_model,\n",
    "        deployment_name=embedding_model,\n",
    "        max_retries=20,\n",
    "    )\n",
    "\n",
    "    context_builder = LocalSearchMixedContext(\n",
    "        community_reports=reports,\n",
    "        text_units=text_units,\n",
    "        entities=entities,\n",
    "        relationships=relationships,\n",
    "        covariates=None,\n",
    "        entity_text_embeddings=description_embedding_store,\n",
    "        embedding_vectorstore_key=EntityVectorStoreKey.ID,\n",
    "        text_embedder=text_embedder,\n",
    "        token_encoder=token_encoder,\n",
    "    )\n",
    "\n",
    "    local_context_params = {\n",
    "        \"text_unit_prop\": 0.5,\n",
    "        \"community_prop\": 0.1,\n",
    "        \"conversation_history_max_turns\": 5,\n",
    "        \"conversation_history_user_turns_only\": True,\n",
    "        \"top_k_mapped_entities\": 10,\n",
    "        \"top_k_relationships\": 10,\n",
    "        \"include_entity_rank\": True,\n",
    "        \"include_relationship_weight\": True,\n",
    "        \"include_community_rank\": True,\n",
    "        \"return_candidate_context\": True,\n",
    "        \"embedding_vectorstore_key\": EntityVectorStoreKey.ID,\n",
    "        \"max_tokens\": 12_000,\n",
    "    }\n",
    "\n",
    "    llm_params = {\n",
    "        \"max_tokens\": 2_000,\n",
    "        \"temperature\": 0.0,\n",
    "    }\n",
    "\n",
    "    search_engine = LocalSearch(\n",
    "        llm=llm,\n",
    "        context_builder=context_builder,\n",
    "        token_encoder=token_encoder,\n",
    "        llm_params=llm_params,\n",
    "        context_builder_params=local_context_params,\n",
    "        response_type=\"multiple paragraphs\",\n",
    "    )\n",
    "\n",
    "    result = await search_engine.asearch(\"你觉得文档中介绍的决策树算法，哪个算法最有应用前景？用中文回答。\")\n",
    "    display(Markdown(result.response))\n",
    "\n",
    "await localSearch()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python (JiuTian GraphRAG)",
   "language": "python",
   "name": "jiutiangraphrag"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
